using System;
using System.Collections.Generic;
using TTDotNet.Util;
using TTDotNet.Engine.Terrain;

namespace TTDotNet.Engine.Networks
{
    public class RoadNode
    {
        private DDDCoordinate coord;
        private TileType roadType;
        private List<RotateType> rotTypes;
        private RotateType rotateAngle;
        private RoadPathType type;

        public RoadNode(DDDCoordinate coord, RotateType rotType, RoadPathType type)
        {
            this.coord = coord;
            this.roadType = TileType.RoadHalf;
            this.type = type;
            rotTypes = new List<RotateType>();

            rotTypes.Add(rotType);
            rotateAngle = rotType;
        }

        public bool AddToNode(RotateType newRotType)
        {
            if (!(rotTypes.Contains(newRotType)))
            {
                rotTypes.Add(newRotType);
            }
            else { return false; }

            CalculateRoadType();
            CalculateRotateAngle();
            return true;
        }

        public DDDCoordinate Coordinate 
        {
            get { return coord; }
        }

        public TileType RoadType
        {
            get { return roadType; }
        }

        public RotateType RotateAngle
        {
            get { return rotateAngle; }
        }

        public RoadPathType NodeType
        {
            get { return type; }
        }

        public List<RotateType> RotateTypes
        {
            get { return rotTypes; }
        }

        public bool Contains(RotateType rotType)
        {
            return rotTypes.Contains(rotType);
        }

        public bool CanConnectTo(RoadNode node)
        {
            DDDCoordinate otherCoord = node.Coordinate;

            if (coord.AdjacentTo(otherCoord))
            {
                if (coord.X == otherCoord.X)
                {
                    if (coord.Z > otherCoord.Z)
                    {
                        return (rotTypes.Contains(RotateType.OneEighty) && node.RotateTypes.Contains(RotateType.Zero));
                    }
                    else
                    {
                        return (rotTypes.Contains(RotateType.Zero) && node.RotateTypes.Contains(RotateType.OneEighty));
                    }
                }
                else if (coord.Z == otherCoord.Z)
                {
                    if (coord.X > otherCoord.X)
                    {
                        return (rotTypes.Contains(RotateType.TwoSeventy) && node.RotateTypes.Contains(RotateType.Ninety));
                    }
                    else
                    {
                        return (rotTypes.Contains(RotateType.Ninety) && node.RotateTypes.Contains(RotateType.TwoSeventy));
                    }
                }
            }

            return false;
        }

        private void CalculateRoadType()
        {
            if (rotTypes.Count == 1) roadType = TileType.RoadHalf;
            else if (rotTypes.Count == 2) {
                if ((((int)rotTypes[0] + (int)rotTypes[1]) % 2) == 0)
                {
                    roadType = TileType.RoadStraight;
                }
                else
                {
                    roadType = TileType.RoadCorner;
                }
            }
            else if (rotTypes.Count == 3) roadType = TileType.RoadJunction;
            else roadType = TileType.RoadCrossroads;

        }

        private void CalculateRotateAngle()
        {
            if (roadType.Equals(TileType.RoadHalf))
            {
                rotateAngle = rotTypes[0];
            }

            if (roadType.Equals(TileType.RoadStraight))
            {
                rotateAngle = rotTypes[0];

                if ((int)rotateAngle > 1)
                {
                    rotateAngle = (RotateType)((int)rotateAngle - 2);
                }
            }

            if (roadType.Equals(TileType.RoadCorner))
            {
                if (rotTypes.Contains(RotateType.Zero) && rotTypes.Contains(RotateType.Ninety)) { 
                    rotateAngle = RotateType.Zero;
                }
                else if (rotTypes.Contains(RotateType.Ninety) && rotTypes.Contains(RotateType.OneEighty)) { 
                    rotateAngle = RotateType.Ninety;
                }
                else if (rotTypes.Contains(RotateType.OneEighty) && rotTypes.Contains(RotateType.TwoSeventy)) { 
                    rotateAngle = RotateType.OneEighty;
                }
                else { rotateAngle = RotateType.TwoSeventy; }
            }

            if (roadType.Equals(TileType.RoadJunction))
            {
                if (!(rotTypes.Contains(RotateType.Zero))) { rotateAngle = RotateType.Ninety; }
                else if (!(rotTypes.Contains(RotateType.Ninety))) { rotateAngle = RotateType.OneEighty; }
                else if (!(rotTypes.Contains(RotateType.OneEighty))) { rotateAngle = RotateType.TwoSeventy; }
                else { rotateAngle = RotateType.Zero; }
            }

            if (roadType.Equals(TileType.RoadCrossroads)) { rotateAngle = RotateType.Zero; }
        }

        public override bool Equals(object obj)
        {
            RoadNode node = (RoadNode)obj;

            return coord.Equals(node.Coordinate);
            
        }

    }
}
